using Microsoft.Extensions.Logging;
using SeataNet.Core.Common;
using SeataNet.Core.Protocol;
using SeataNet.Core.RPC;
using System.Collections.Concurrent;

namespace SeataNet.Core.Saga
{
  /// <summary>
  /// Saga事务管理器接口
  /// </summary>
  public interface ISagaTransactionManager
  {
    /// <summary>
    /// 开始Saga事务
    /// </summary>
    /// <param name="timeoutMs">超时时间（毫秒）</param>
    /// <param name="name">事务名称</param>
    /// <returns>事务开始结果</returns>
    Task<TransactionBeginResult> BeginAsync(int timeoutMs = 60000, string? name = null);

    /// <summary>
    /// 提交Saga事务
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <returns>事务提交结果</returns>
    Task<TransactionCommitResult> CommitAsync(string xid);

    /// <summary>
    /// 提交Saga事务（同步版本）
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <returns>事务提交结果</returns>
    TransactionCommitResult Commit(string xid);

    /// <summary>
    /// 回滚Saga事务
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <returns>事务回滚结果</returns>
    Task<TransactionRollbackResult> RollbackAsync(string xid);

    /// <summary>
    /// 回滚Saga事务（同步版本）
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <returns>事务回滚结果</returns>
    TransactionRollbackResult Rollback(string xid);

    /// <summary>
    /// 注册Saga步骤
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <param name="stepName">步骤名称</param>
    /// <param name="compensationMethod">补偿方法</param>
    /// <param name="input">输入参数</param>
    /// <returns>步骤注册结果</returns>
    Task<SagaStepRegisterResult> RegisterStepAsync(string xid, string stepName, string compensationMethod, object input);

    /// <summary>
    /// 报告Saga步骤状态
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <param name="stepId">步骤ID</param>
    /// <param name="status">步骤状态</param>
    /// <param name="output">输出结果</param>
    /// <returns>状态报告结果</returns>
    Task<SagaStepReportResult> ReportStepStatusAsync(string xid, string stepId, SagaStepStatus status, object output);

    /// <summary>
    /// 获取Saga事务上下文
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <returns>事务上下文</returns>
    SagaTransactionContext GetTransactionContext(string xid);

    /// <summary>
    /// 获取Saga步骤上下文
    /// </summary>
    /// <param name="xid">事务XID</param>
    /// <param name="stepId">步骤ID</param>
    /// <returns>步骤上下文</returns>
    SagaStepContext GetStepContext(string xid, string stepId);
  }

  /// <summary>
  /// 默认Saga事务管理器实现
  /// </summary>
  public class DefaultSagaTransactionManager(
      ILogger<DefaultSagaTransactionManager> logger,
      IRpcClientManager rpcClientManager,
      ISagaStateStore stateStore) : ISagaTransactionManager
  {
    private readonly ILogger<DefaultSagaTransactionManager> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    private readonly IRpcClientManager _rpcClientManager = rpcClientManager ?? throw new ArgumentNullException(nameof(rpcClientManager));
    private readonly ISagaStateStore _stateStore = stateStore ?? throw new ArgumentNullException(nameof(stateStore));
    private readonly ConcurrentDictionary<string, SagaTransactionContext> _transactionContexts = new();
    private readonly ConcurrentDictionary<string, List<SagaStepContext>> _stepContexts = new();

    public async Task<TransactionBeginResult> BeginAsync(int timeoutMs = 60000, string? name = null)
    {
      try
      {
        _logger.LogDebug($"开始Saga事务: Timeout={timeoutMs}, Name={name}");

        // 创建全局事务开始请求
        GlobalBeginRequest request = new()
        {
          TransactionName = name ?? "saga-transaction",
          Timeout = timeoutMs
        };

        // 获取TC客户端
        IRpcClient tcClient = await _rpcClientManager.GetRpcClientAsync("TC");
        if (tcClient == null)
        {
          return new TransactionBeginResult
          {
            Success = false,
            Message = "无法获取TC客户端"
          };
        }

        // 发送请求
        var response = await tcClient.SendAsync<GlobalBeginRequest, GlobalBeginResponse>(request);
        if (response == null)
        {
          return new TransactionBeginResult
          {
            Success = false,
            Message = "TC服务器无响应"
          };
        }

        // 创建事务上下文
        SagaTransactionContext context = new()
        {
          Xid = response.Xid,
          TransactionId = response.TransactionId,
          TransactionName = name ?? "saga-transaction",
          Status = SagaTransactionStatus.Active,
          StartTime = DateTime.UtcNow,
          Timeout = timeoutMs
        };

        // 保存事务上下文
        _transactionContexts.TryAdd(response.Xid, context);
        _stepContexts.TryAdd(response.Xid, new List<SagaStepContext>());

        // 持久化事务状态
        await _stateStore.SaveTransactionContextAsync(context);

        _logger.LogDebug($"Saga事务已开始: XID={response.Xid}");

        return new TransactionBeginResult
        {
          Success = true,
          Xid = response.Xid,
          TransactionId = response.TransactionId
        };
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, "开始Saga事务时发生异常");
        return new TransactionBeginResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public async Task<TransactionCommitResult> CommitAsync(string xid)
    {
      try
      {
        _logger.LogDebug($"提交Saga事务: XID={xid}");

        // 获取事务上下文
        SagaTransactionContext context = GetTransactionContext(xid);
        if (context == null)
        {
          return new TransactionCommitResult
          {
            Success = false,
            Message = $"找不到事务上下文: XID={xid}"
          };
        }

        // 创建全局事务提交请求
        GlobalCommitRequest request = new()
        {
          Xid = xid
        };

        // 获取TC客户端
        IRpcClient tcClient = await _rpcClientManager.GetRpcClientAsync("TC");
        if (tcClient == null)
        {
          return new TransactionCommitResult
          {
            Success = false,
            Message = "无法获取TC客户端"
          };
        }

        // 发送请求
        var response = await tcClient.SendAsync<GlobalCommitRequest, GlobalCommitResponse>(request);
        if (response == null)
        {
          return new TransactionCommitResult
          {
            Success = false,
            Message = "TC服务器无响应"
          };
        }

        // 更新事务状态
        context.Status = response.GlobalStatus == GlobalStatus.Committed ?
            SagaTransactionStatus.Committed :
            SagaTransactionStatus.Failed;
        context.EndTime = DateTime.UtcNow;

        // 持久化事务状态
        await _stateStore.UpdateTransactionContextAsync(context);

        _logger.LogDebug($"Saga事务已提交: XID={xid}, Status={response.GlobalStatus}");

        return new TransactionCommitResult
        {
          Success = response.GlobalStatus == GlobalStatus.Committed,
          Message = response.GlobalStatus == GlobalStatus.Committed ? "提交成功" : "提交失败"
        };
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"提交Saga事务时发生异常: XID={xid}");
        return new TransactionCommitResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public TransactionCommitResult Commit(string xid)
    {
      try
      {
        // 使用同步方式调用异步方法
        return CommitAsync(xid).GetAwaiter().GetResult();
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"同步提交Saga事务时发生异常: XID={xid}");
        return new TransactionCommitResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public async Task<TransactionRollbackResult> RollbackAsync(string xid)
    {
      try
      {
        _logger.LogDebug($"回滚Saga事务: XID={xid}");

        // 获取事务上下文
        SagaTransactionContext context = GetTransactionContext(xid);
        if (context == null)
        {
          return new TransactionRollbackResult
          {
            Success = false,
            Message = $"找不到事务上下文: XID={xid}"
          };
        }

        // 执行补偿操作
        List<SagaStepContext> stepContexts = _stepContexts.GetValueOrDefault(xid, []);
        var completedSteps = stepContexts.Where(static s => s.Status == SagaStepStatus.Completed).Reverse().ToList();

        foreach (var step in completedSteps)
        {
          try
          {
            _logger.LogDebug($"执行补偿操作: XID={xid}, StepId={step.StepId}, CompensationMethod={step.CompensationMethod}");

            // 执行补偿方法
            var compensationResult = await ExecuteCompensationAsync(step);
            if (compensationResult)
            {
              step.Status = SagaStepStatus.Compensated;
              _logger.LogDebug($"补偿操作成功: XID={xid}, StepId={step.StepId}");
            }
            else
            {
              step.Status = SagaStepStatus.CompensationFailed;
              _logger.LogError($"补偿操作失败: XID={xid}, StepId={step.StepId}");
            }
          }
          catch (Exception ex)
          {
            step.Status = SagaStepStatus.CompensationFailed;
            _logger.LogError(ex, $"补偿操作异常: XID={xid}, StepId={step.StepId}");
          }
        }

        // 创建全局事务回滚请求
        GlobalRollbackRequest request = new()
        {
          Xid = xid
        };

        // 获取TC客户端
        IRpcClient tcClient = await _rpcClientManager.GetRpcClientAsync("TC");
        if (tcClient == null)
        {
          return new TransactionRollbackResult
          {
            Success = false,
            Message = "无法获取TC客户端"
          };
        }

        // 发送请求
        var response = await tcClient.SendAsync<GlobalRollbackRequest, GlobalRollbackResponse>(request);
        if (response == null)
        {
          return new TransactionRollbackResult
          {
            Success = false,
            Message = "TC服务器无响应"
          };
        }

        // 更新事务状态
        context.Status = response.GlobalStatus == GlobalStatus.Rollbacked ?
            SagaTransactionStatus.RolledBack :
            SagaTransactionStatus.Failed;
        context.EndTime = DateTime.UtcNow;

        // 持久化事务状态
        await _stateStore.UpdateTransactionContextAsync(context);

        _logger.LogDebug($"Saga事务已回滚: XID={xid}, Status={response.GlobalStatus}");

        return new TransactionRollbackResult
        {
          Success = response.GlobalStatus == GlobalStatus.Rollbacked,
          Message = response.GlobalStatus == GlobalStatus.Rollbacked ? "回滚成功" : "回滚失败"
        };
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"回滚Saga事务时发生异常: XID={xid}");
        return new TransactionRollbackResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public TransactionRollbackResult Rollback(string xid)
    {
      try
      {
        // 使用同步方式调用异步方法
        return RollbackAsync(xid).GetAwaiter().GetResult();
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"同步回滚Saga事务时发生异常: XID={xid}");
        return new TransactionRollbackResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public async Task<SagaStepRegisterResult> RegisterStepAsync(string xid, string stepName, string compensationMethod, object input)
    {
      try
      {
        _logger.LogDebug($"注册Saga步骤: XID={xid}, StepName={stepName}, CompensationMethod={compensationMethod}");

        // 获取事务上下文
        SagaTransactionContext context = GetTransactionContext(xid);
        if (context == null)
        {
          return new SagaStepRegisterResult
          {
            Success = false,
            Message = $"找不到事务上下文: XID={xid}"
          };
        }

        // 创建步骤上下文
        string stepId = Guid.NewGuid().ToString();
        SagaStepContext stepContext = new()
        {
          StepId = stepId,
          StepName = stepName,
          CompensationMethod = compensationMethod,
          Input = input,
          Status = SagaStepStatus.Registered,
          CreatedTime = DateTime.UtcNow
        };

        // 保存步骤上下文
        List<SagaStepContext> steps = _stepContexts.GetOrAdd(xid, static _ => []);
        lock (steps)
        {
          steps.Add(stepContext);
        }

        // 持久化步骤状态
        await _stateStore.SaveStepContextAsync(xid, stepContext);

        _logger.LogDebug($"Saga步骤已注册: XID={xid}, StepId={stepId}");

        return new SagaStepRegisterResult
        {
          Success = true,
          StepId = stepId
        };
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"注册Saga步骤时发生异常: XID={xid}, StepName={stepName}");
        return new SagaStepRegisterResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public async Task<SagaStepReportResult> ReportStepStatusAsync(string xid, string stepId, SagaStepStatus status, object output)
    {
      try
      {
        _logger.LogDebug($"报告Saga步骤状态: XID={xid}, StepId={stepId}, Status={status}");

        // 获取步骤上下文
        SagaStepContext stepContext = GetStepContext(xid, stepId);
        if (stepContext == null)
        {
          return new SagaStepReportResult
          {
            Success = false,
            Message = $"找不到步骤上下文: XID={xid}, StepId={stepId}"
          };
        }

        // 更新步骤状态
        stepContext.Status = status;
        stepContext.Output = output;
        stepContext.UpdatedTime = DateTime.UtcNow;

        // 持久化步骤状态
        await _stateStore.UpdateStepContextAsync(xid, stepContext);

        _logger.LogDebug($"Saga步骤状态已报告: XID={xid}, StepId={stepId}, Status={status}");

        return new SagaStepReportResult
        {
          Success = true
        };
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"报告Saga步骤状态时发生异常: XID={xid}, StepId={stepId}");
        return new SagaStepReportResult
        {
          Success = false,
          Message = ex.Message
        };
      }
    }

    public SagaTransactionContext GetTransactionContext(string xid)
    {
      _ = _transactionContexts.TryGetValue(xid, out SagaTransactionContext? context);
      return context;
    }

    public SagaStepContext GetStepContext(string xid, string stepId)
    {
      List<SagaStepContext>? steps = _stepContexts.GetValueOrDefault(xid);
      return steps?.FirstOrDefault(s => s.StepId == stepId);
    }

    private async Task<bool> ExecuteCompensationAsync(SagaStepContext stepContext)
    {
      try
      {
        // 根据补偿方法名称获取方法信息
        Type serviceType = Type.GetType(stepContext.ServiceName);
        if (serviceType == null)
        {
          _logger.LogError($"找不到服务类型: {stepContext.ServiceName}");
          return false;
        }

        System.Reflection.MethodInfo method = serviceType.GetMethod(stepContext.CompensationMethod);
        if (method == null)
        {
          _logger.LogError($"找不到补偿方法: {stepContext.CompensationMethod}");
          return false;
        }

        // 创建服务实例
        object? service = Activator.CreateInstance(serviceType);
        if (service == null)
        {
          _logger.LogError($"无法创建服务实例: {stepContext.ServiceName}");
          return false;
        }

        // 执行补偿方法
        object result = method.Invoke(service, new[] { stepContext.Input });

        // 如果是异步方法，等待结果
        if (result is Task task)
        {
          await task;

          // 获取Task<bool>的结果
          Type taskType = task.GetType();
          if (taskType.IsGenericType && taskType.GetGenericTypeDefinition() == typeof(Task<>))
          {
            System.Reflection.PropertyInfo? resultProperty = taskType.GetProperty("Result");
            if (resultProperty?.GetValue(task) is bool boolResult)
            {
              return boolResult;
            }
          }

          return true;
        }

        // 如果返回bool，直接返回结果
        return result is not bool boolResultValue || boolResultValue;
      }
      catch (Exception ex)
      {
        _logger.LogError(ex, $"执行补偿操作异常: StepId={stepContext.StepId}, CompensationMethod={stepContext.CompensationMethod}");
        return false;
      }
    }
  }
}